#include "NatDebtDataModel.h"
#include "bondlib/BondCDCPriceInfo.h"
#include "core/Utility.h"
#include "tfBondInfo.h"
#include <map>
#include <vector>
#include "uam/UserAccountManager.h"
#include <core/strings/string_util.h>
//#include "qbbond/Detail/BondDetailData.h"
// #include "../bonddeal/TransactionTools.h"
// #include "../NewDetail/NewDetailTestTime.h"
using namespace calcutfRate;
//#include "../NewDetail/NewDetailTestTime.h"

CNatTFKData::~CNatTFKData()
{
	Clear();
}

void CNatTFKData::Clear()
{
// 	for(map<QString,CBondData*>::const_iterator itr = m_mapKData.begin(); itr != m_mapKData.end() ;  ++itr){
// 		CBondData* pData = itr->second;
// 		pData->Clear();
// 		if(pData) delete pData;
// 		pData = NULL;
// 	}
// 	m_mapKData.clear();
// 	m_mapTFCCList.clear();
	//m_mapTFCCList.clear();
}

// bool CNatTFKData::GetTFBondData(const QString& strTFID, CBondData*& bondData, bool bNeedNew)
// {
// 	if (m_mapKData.find(strTFID) == m_mapKData.end()){
// 		if (bNeedNew){
// 			bondData = new CBondData;
// 			CFutureInfo info;
// 			AfxGetBondFuture().GetFutureInfo(SSW2A(strTFID).c_str(), &info);
// 			bondData->SetFutureInfo(&info);
// 			bondData->SetDatabase(&AfxGetDB());
// 			bondData->SetNetStatus(AfxGetBondReceiver().GetConnected());
// 			//分时图数据
// 			bondData->PrepareData(CBondData::dataQuote, CKData::ktypeDay, true);//涉及到分时图
// 			bondData->PrepareData(CBondData::dataReport, CKData::ktypeDay, true);//没用到？
// 			bondData->PrepareData(CBondData::dataMinute, CKData::ktypeDay, true);//涉及到分时图
// 			AfxPrepareBondData(&AfxGetDB(), bondData, CKData::ktypeDay, CKData::formatOriginal, CKData::mdtypeClose, false, true);
// 			m_mapKData[strTFID] = bondData;
// 		}
// 		return false;
// 	}
// 	bondData = m_mapKData[strTFID];
// 	return true;
// }

// bool CNatTFKData::GetTFBondDataTFCC(CDlgCmpRTGraphics*& pGraphics , const QString& strTFID, CBondData*& bondData, bool bNeedNew/*没有找到是否需要new*/)
// {
// 	if (strTFID.IsEmpty()){
// 		return false;
// 	}
// 	if (m_mapKData.find(strTFID) == m_mapKData.end()){
// 		if (bNeedNew){
// 			bool bContract = false;//是否连续合约
// 			string stCCTFID, stCCTFKey;
// 			CFutureInfo info;
// 			if (!AfxGetBondFuture().GetFutureInfo(SSW2A(strTFID).c_str(), &info) || !info.IsValidFuture()){
// 				CCCFlowManager& ccflow = AfxGetCCFlow();
// 				LockEx::Scoped l(ccflow.GetMutex());
// 				DETAIL_TEST(_T("----------------TF CONNNECT LOCK TIMES"));
// 				const std::set<std::string> setTemp = ccflow.GetTFCIDList();
// 				std::set<std::string>::const_iterator itrSet = setTemp.begin();
// 				for (; itrSet != setTemp.end(); ++itrSet){
// 					CCCFlowInfo* pInfo = const_cast<CCCFlowInfo*> (ccflow.GetCCFlowInfo((*itrSet).c_str()));
// 					if (pInfo && strcmp(pInfo->GetTFCName(), SSW2A(strTFID).c_str()) == 0){
// 						bContract = true;
// 						const std::list<CCFLOWINFOUNIT>& m_list = const_cast<CCCFlowInfo*>(pInfo)->GetFlowInfoList();
// 						std::list<CCFLOWINFOUNIT>::const_reverse_iterator ritCC = m_list.rbegin();
// 						if (ritCC != m_list.rend()){
// 							if (!AfxGetBondFuture().GetFutureInfo(ritCC->TFID, &info) || !info.IsValidFuture()){
// 								LOGINFO("nat tf kdata cc tf id: %s is invalid 1", SSW2A(strTFID).c_str());
// 								return false;
// 							}
// 							stCCTFID = const_cast<CCCFlowInfo*>(pInfo)->GetTFCID();
// 							stCCTFKey = const_cast<CCCFlowInfo*>(pInfo)->GetTFCKey();
// 							FIELDCOPY(info.m_TF_ID, ritCC->TFID);
// 							FIELDCOPY(info.m_InstrumentID, ritCC->TFID); //保存对应合约ID
// 							m_mapTFCCList[strTFID] = m_list;
// 							if (pGraphics)	pGraphics->SetCCFlowList(m_list);//->CDlgCmpRTGraphvw->CCmpBondGraph
// 						}
// 						break;
// 					}
// 				}
// 				if (itrSet == setTemp.end()){
// 					LOGINFO("nat tf kdata cc tf id: %s can't find cc", SSW2A(strTFID).c_str());
// 					return false;
// 				}
// 			}
// 
// 			bondData = new CBondData;
// 			bondData->SetFutureInfo(&info);
// 			bondData->SetDatabase(&AfxGetDB());
// 			bondData->SetNetStatus(AfxGetBondReceiver().GetConnected());
// 
// 			//分时图数据
// 			bondData->PrepareData(CBondData::dataQuote, CKData::ktypeDay, true);//涉及到分时图
// 			bondData->PrepareData(CBondData::dataReport, CKData::ktypeDay, true);//没用到？
// 			bondData->PrepareData(CBondData::dataMinute, CKData::ktypeDay, true);//涉及到分时图
// 
// 			if (bContract){
// 				CFutureInfo& fi = bondData->GetFutureInfo();
// 				FIELDCOPY(fi.m_TF_Key, stCCTFKey.c_str());
// 				FIELDCOPY(fi.m_TF_ID, stCCTFID.c_str());
// 			}
// 			AfxPrepareBondData(&AfxGetDB(), bondData, CKData::ktypeDay, CKData::formatOriginal, CKData::mdtypeClose, false, true);
// 			m_mapKData[strTFID] = bondData;
// 		}
// 		return false;
// 	}
// 	bondData = m_mapKData[strTFID];
// 	return true;
// }

bool CNatDebtCEDeal::Clear(){
	m_list.clear();
	m_mapCFETSDeal.clear();
	return true;
}

bool CNatDebtCEDeal::InsertData(xQBMarketStreamList_c* pLstdata){
	if(!pLstdata) return false;
	const size_t nSize = pLstdata->m_List.size();
	if(nSize==0) return false;
	for(std::list<xQBMarketStreamUnit_c>::iterator it = pLstdata->m_List.begin();
		it!=pLstdata->m_List.end(); ++it){
		InsetUnitData(*it);
	}
	return true;
}

bool CNatDebtCEDeal::InsertData(xSingleBondQuotationAck_c* pLstdata){
	if (!pLstdata || strcmp(pLstdata->m_Source,"c") != 0) return false;
	if (strcmp(pLstdata->ListedMarket, CBondContainer::lmCIB) != 0) return false;
	xSingleBondQuotationAck_c ack = *pLstdata;
	m_mapCFETSDeal[ack.BondKey] = ack;
	return true;
}

void CNatDebtCEDeal::InsetUnitData(const xQBMarketStreamUnit_c& unit){
	MarketStreamInfo msinfo;
	if (0 != strcmp("2", unit.m_type)) return;
	if (strcmp(unit.m_company_id, "e") == 0) {
		if (unit.m_body2.m_tradeMode[0] != '\0' && unit.m_body2.m_tradeMode[0] != '1') {
			return; //交易所仅匹配成交类型为“匹配成交”
		}
	}
	if (strcmp(unit.m_company_id, "e") != 0 && strcmp(unit.m_company_id, "c") != 0 && strcmp(unit.m_company_id, NEW_DETAIL_CFETS_BROKER_STRING) != 0) return;
	//if (!IsNationalBond(unit.m_body2.m_bondkey, unit.m_body2.m_listedmarket)) return;
	memset(&msinfo, 0, sizeof(MarketStreamInfo));
	FIELDCOPY(msinfo.m_company_id,unit.m_company_id);
	//FIELDCOPY(msinfo.m_company_name,unit.m_company_name);
	FIELDCOPY(msinfo.m_dept,unit.m_dept);
	FIELDCOPY(msinfo.m_type,unit.m_type);
	FIELDCOPY(msinfo.m_operate,unit.m_operate);
	//FIELDCOPY(msinfo.m_status,unit.m_status);
	msinfo.m_modify_time = unit.m_modify_time;
	msinfo.m_create_time = unit.m_create_time;
	msinfo.m_indexID = unit.m_indexID;

	//if(strcmp(CBondContainer::lmCIB,unit.m_body2.m_listedmarket) != 0) continue;
	//FIELDCOPY(msinfo.m_body.m_bondCode,unit.m_body2.m_bondCode);
	FIELDCOPY(msinfo.m_body.m_bondkey,unit.m_body2.m_bondkey);
	FIELDCOPY(msinfo.m_body.m_listedmarket,unit.m_body2.m_listedmarket);
	//FIELDCOPY(msinfo.m_body.m_bondShortName,unit.m_body2.m_bondShortName);
	FIELDCOPY(msinfo.m_body.m_price,unit.m_body2.m_price);
	FIELDCOPY(msinfo.m_body.m_volume,unit.m_body2.m_volume);
	FIELDCOPY(msinfo.m_body.m_fullPrice,unit.m_body2.m_fullPrice);
	FIELDCOPY(msinfo.m_body.m_cleanPrice,unit.m_body2.m_cleanPrice);
	FIELDCOPY(msinfo.m_body.m_yield,unit.m_body2.m_yield);
	FIELDCOPY(msinfo.m_body.m_rebate,unit.m_body2.m_rebate);
	FIELDCOPY(msinfo.m_body.m_return_point,unit.m_body2.m_return_point);
	FIELDCOPY(msinfo.m_body.m_id,unit.m_body2.m_id);
	FIELDCOPY(msinfo.m_body.m_dealStatus,unit.m_body2.m_dealStatus);
	msinfo.m_body.m_createTime = unit.m_body2.m_createTime;
	FIELDCOPY(msinfo.m_body.m_exercise,unit.m_body2.m_exercise);
	if (strlen(msinfo.m_body.m_price) <= 0 && strlen(msinfo.m_body.m_cleanPrice) > 0){
		FIELDCOPY(msinfo.m_body.m_price, msinfo.m_body.m_cleanPrice);
	}
	Insert(msinfo);
}

bool  CNatDebtCEDeal::Insert(MarketStreamInfo &info){
	if (atoi(info.m_type) != 2) return 0;
	int nDealStatus = atoi(info.m_body.m_dealStatus);
	std::list<MarketStreamInfo>::iterator itr = m_list.begin();
	for(;itr!=m_list.end();){
		if(strcmp(itr->m_body.m_id,info.m_body.m_id)==0){
			if(nDealStatus<4){
				*itr = info;
				return true;
			}
			else{
				m_list.erase(itr++);
				return true;
			}
		}
		++itr;
	}
	if(nDealStatus >=4 )return false;
	m_list.push_back(info);
	m_list.sort();
	return true;
}

bool CNatDebtCEDeal::GetMarketStreamByKey(const char * szBondKey,const char * szBroker, MarketInfo &stInfo){
	int bondIndex = CBondContainer::instance().GetBondIndex(szBondKey);
	if (!CBondContainer::instance().IsValidIndex(bondIndex))return false;
	const CBondInfo& bond = CBondContainer::instance().ElementAtR(bondIndex);
	return GetMarketStreamByKey(bond.GetBondKey(),bond.GetListedMarket(),szBroker,stInfo);
}

bool CNatDebtCEDeal::GetMarketStreamByKey(const char * szBondKey, const char * szListMarket, const char * szBroker, MarketInfo &stInfo){
	if (VERIRY_IS_CFETST_BROKER_STRING(szBroker)){
		if (szBondKey[0] == '\0' || szListMarket[0] == '\0') return false;
		std::map<std::string, xSingleBondQuotationAck_c>::const_iterator itrFind = m_mapCFETSDeal.find(szBondKey);
		if (itrFind == m_mapCFETSDeal.end()) return false;
		stInfo.m_body.m_createTime = stInfo.m_create_time = stInfo.m_modify_time = itrFind->second.m_time;
		FIELDCOPY(stInfo.m_body.m_price, itrFind->second.m_Price);
		return true;
	}
	else if (VERIRY_IS_EXCHANGE_BROKER_STRING(szBroker) || VERIRY_IS_EXCHANGE_BROKER_INT(atoi(szBroker))){
		if (m_list.size() <= 0) return false;
		std::list<MarketStreamInfo>::iterator itr = m_list.begin();
		for (; itr != m_list.end(); ++itr){
			if (strcmp(itr->m_body.m_bondkey, szBondKey) == 0 &&strcmp(itr->m_body.m_listedmarket, szListMarket) == 0){
				stInfo = *itr;
				return true;
			}
		}
	}
	return false;
}

bool CNatDebtCEDeal::IsNationalBond(const char* key,const char * market){
	if(!key || !market) return false;

	int bondIndex = CBondContainer::instance().GetBondIndex(key, market);
	if (!CBondContainer::instance().IsValidIndex(bondIndex))return false;
	const CBondInfo& bond = CBondContainer::instance().ElementAtR(bondIndex);
	std::string strType = bond.GetBondSubType();
	if (strType.compare("BGB") == 0 || strType.compare("SGB") == 0 || strType.compare("EGB") == 0) return true;
	return false;
}

// int CALLBACK BasisSort(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort)//基差排序
// {
// 	UNUSED_ALWAYS(lParamSort);
// 
// 	CGridCellBase* pCell1 = (CGridCellBase*) lParam1;
// 	CGridCellBase* pCell2 = (CGridCellBase*) lParam2;
// 	if (!pCell1 || !pCell2) return 0;
// 	CGridCtrl* pGrid = pCell1->GetGrid();
// 	bool bAscend = false;
// 	if(pGrid && pGrid->GetSafeHwnd())
// 	{
// 		bAscend = pGrid->GetSortAscending();
// 	}
// 	QString szFirst1 = CSSTools::GetFirstLetter(pCell1->FuncGT1());
// 	QString szFirst2 = CSSTools::GetFirstLetter(pCell2->FuncGT1());
// 
// 	if(szFirst1.Compare(_T("--")) == 0 && szFirst2.Compare(_T("--")) == 0)
// 		return 0;
// 	else if(szFirst1.Compare(_T("--")) == 0 && szFirst2.Compare(_T("--")) != 0)
// 	{
// 		if(bAscend) return 1;
// 		else  return -1;
// 	}
// 	else if(szFirst1.Compare(_T("--")) != 0 && szFirst2.Compare(_T("--")) == 0)
// 	{
// 		if(bAscend) return -1;
// 		else  return 1;
// 	}
// 
// 	std::string sFirst1 = SSW2A(szFirst1);
// 	std::string sFirst2 = SSW2A(szFirst2);
// 
// 	float fFirst1 = atof(sFirst1.c_str());//RatingsConvert(szFirst1);
// 	float fFirst2 = atof(sFirst2.c_str());
// 
// 	if(fFirst1 > fFirst2)
// 		return 1;
// 	else if(fFirst1 <fFirst2)
// 		return -1;
// 	else
// 		return 0;
// }

std::string  GetClearDay(){
	QDateTime ctm = QDateTime::fromTime_t(CSSVContainer::GetServerTime());
	std::string strClearing = qb::base::string_format("%4d%02d%02d",ctm.date().year(),ctm.date().month(),ctm.date().day());
	return strClearing;
}

bool VerifyValidCalculate(double data,bool bNeedZero){
	if((data > -99899.00 || data < -99901.00) &&
	   (data > -998.99 || data < -999.01)&&
	   (bNeedZero || (!bNeedZero && (data > 0.0000001 || data < -0.0000001)))
	   ) return true;
	return false;
}

int TimeToMinutInt(time_t tTm){
	if (tTm <= 0) return 0;
	QDateTime timeTemp = QDateTime::fromTime_t(tTm);
	return timeTemp.date().day() * 10000 + timeTemp.time().hour() * 100 + timeTemp.time().minute();
}

int  AutoTimeToDM(time_t tTm)
{
	unsigned int nCurrentDate = qb::base::IntDate::timeToInt(tTm);
	if(qb::base::IntDate::timeToInt(CSSVContainer::GetServerTime()) > nCurrentDate) return nCurrentDate;
	else return TimeToMinutInt(tTm);
}

void TransformCFETSDeal(const xSingleBondQuotationAck_c& ackIn, xQBMarketStreamUnit_c& unitOut)
{
	FIELDCOPY(unitOut.m_type, "2");
	FIELDCOPY(unitOut.m_status, "0");
	FIELDCOPY(unitOut.m_company_id, NEW_DETAIL_CFETS_BROKER_STRING);
	unitOut.m_body2.m_createTime = unitOut.m_create_time = unitOut.m_modify_time = ackIn.m_time;
	FIELDCOPY(unitOut.m_body2.m_price, ackIn.m_Price);
	FIELDCOPY(unitOut.m_body2.m_dealStatus, "0");
	FIELDCOPY(unitOut.m_body2.m_bondkey, ackIn.BondKey);
	FIELDCOPY(unitOut.m_body2.m_listedmarket, ackIn.ListedMarket);
}

time_t GetBondEstTime(const char * cBondKey,std::string& strEstPrc)
{
	time_t tTime = 0;
	UINT unEstDate = 0;
	std::string strKey;	strKey = qb::base::string_format("%s.%s", cBondKey, CBondContainer::lmCIB);
	CBondInfo* pInfo = CBondContainer::instance().GetBond(strKey.c_str());
	int nBondIndex = CBondContainer::instance().GetBondIndex(strKey.c_str());
	int optType;
	if(pInfo&&pInfo->IsValidBond()){
		strEstPrc = qb::base::string_format("%s", (CBondCDCPriceInfo::instance().GetCDCPriceYesterday(optType, pInfo->IsCDCAuthValid(), nBondIndex, CBondCDCPriceInfo::price_type_yield, true).c_str()));
		unEstDate = CBondCDCPriceInfo::instance().GetEstimateDate(nBondIndex);
	}
	else{
		strKey = qb::base::string_format("%s.%s", cBondKey, CBondContainer::lmSSE);
		pInfo = CBondContainer::instance().GetBond(strKey.c_str());
		nBondIndex = CBondContainer::instance().GetBondIndex(strKey.c_str());
		if(pInfo&&pInfo->IsValidBond()){
			strEstPrc = qb::base::string_format("%s", CBondCDCPriceInfo::instance().GetCDCPriceYesterday(optType, pInfo->IsCDCAuthValid(), nBondIndex, CBondCDCPriceInfo::price_type_yield, true).c_str());
			unEstDate = CBondCDCPriceInfo::instance().GetEstimateDate(nBondIndex);
		}
		else{
			strKey = qb::base::string_format("%s.%s", cBondKey, CBondContainer::lmSZE);
			pInfo = CBondContainer::instance().GetBond(strKey.c_str());
			nBondIndex = CBondContainer::instance().GetBondIndex(strKey.c_str());
			if(pInfo&&pInfo->IsValidBond()){
				strEstPrc = qb::base::string_format("%s", CBondCDCPriceInfo::instance().GetCDCPriceYesterday(optType, pInfo->IsCDCAuthValid(), nBondIndex, CBondCDCPriceInfo::price_type_yield, true).c_str());
				unEstDate = CBondCDCPriceInfo::instance().GetEstimateDate(nBondIndex);
			}
		}
	}
	if(unEstDate > 0){
		tTime = qb::base::IntDate::IntToTime(unEstDate);
	}
	return tTime;
}

void CNatDebtDealTFTmPrc::InsertTFPrc(time_t tTm , const char* cPrc)
{
	int nTime = AutoTimeToDM(tTm);
	if(nTime > 0) m_mapPrc[nTime] = cPrc;
}

float CNatDebtDealTFTmPrc::GetPrc(time_t tTm, std::string& strPrc)
{
	strPrc = "--";
	int nTime = AutoTimeToDM(tTm);
	if(nTime > 0 && m_mapPrc.find(nTime) != m_mapPrc.end()){
		//TranslateDonePrice(m_mapPrc[nTime].c_str(),strPrc);
		return atof(m_mapPrc[nTime].c_str());
	}
	return 0.0f;
}

CNatDebtDealTFPrc::CNatDebtDealTFPrc(){
	m_nDataDate = qb::base::IntDate::timeToInt(CSSVContainer::GetServerTime());
}

void CNatDebtDealTFPrc::Clear(){
	if (m_nDataDate == qb::base::IntDate::timeToInt(CSSVContainer::GetServerTime())){//当天不需要清除
		return;
	}
	m_mapInfo.clear();
}

float CNatDebtDealTFPrc::GetTFPrice(const std::string& strTFId, time_t tTime, std::string& strPrc){
	if (m_mapInfo.find(strTFId) != m_mapInfo.end()){
		return m_mapInfo[strTFId].GetPrc(tTime, strPrc);
	}
	return 0.0f;
}

void CNatDebtDealTFPrc::Initial(std::vector<CFutureInfo>& tf){
	CNatDebtDealTFTmPrc prc;
	int nCnt = tf.size();
	std::string strTFId;
	for(int nL = 0 ; nL < nCnt ; nL ++){
		strTFId = qb::base::string_format("%s", tf[nL].m_TF_ID);
		m_mapInfo.insert(std::pair<std::string,CNatDebtDealTFTmPrc>(strTFId,prc));
	}
}

void CNatDebtDealTFPrc::InsertTFPrc(const std::string& strTFId, time_t tTime, const char* cPrc){
	if(m_mapInfo.find(strTFId) != m_mapInfo.end()){
		CNatDebtDealTFTmPrc& prc = m_mapInfo[strTFId];
		prc.InsertTFPrc(tTime, cPrc);
	}
}

void  CNatDebtDealTFPrc::InsertTFPrc(time_t tTime, const char* cPrc)
{
	for(map<std::string/*TFID*/,CNatDebtDealTFTmPrc>::iterator itr = m_mapInfo.begin()
		; itr != m_mapInfo.end(); ++itr){
		CNatDebtDealTFTmPrc& prc = itr->second;
		prc.InsertTFPrc(tTime,cPrc);
	}	
}

void CNatDebtDealTFPrc::InsertTFPrc(xNatDebtDealTFPrc_Req_t* prcReq)
{
	if(!prcReq) return;
	int nTime;
	for(std::list<xNatDebtDealTFPrc_Unit>::const_iterator itrUnit = prcReq->m_List.begin();
		itrUnit != prcReq->m_List.end();  ++itrUnit){
		CNatDebtDealTFTmPrc& prc = m_mapInfo[itrUnit->m_TF_ID];
		for(std::list<xNatDebtDealTFPrc_Unit_c>::const_iterator itrPrc = itrUnit->m_List.begin();
			itrPrc != itrUnit->m_List.end();  ++itrPrc){
			nTime = AutoTimeToDM(itrPrc->m_Time);
			prc.m_mapPrc[nTime] = itrPrc->m_price;
			//QString strTemp;
			//strTemp.Format(_T("----添加TF价格--time:%d pric:%s\r\n"), nTime, SSA2W(itrPrc->m_price));
			//OutputDebugString(strTemp);
		}
	}
}

bool CNatDebtDealTFPrc::HaveReqPrc(const std::string& strTFId, time_t tTime)
{
	if(tTime > 0 ){
		int nTime = AutoTimeToDM(tTime);
		if(m_mapInfo.find(strTFId) != m_mapInfo.end()){
			CNatDebtDealTFTmPrc& tfPrc = m_mapInfo[strTFId];
			if(tfPrc.m_mapPrc.find(nTime) != tfPrc.m_mapPrc.end()) return true;
		}
	}
	return false;
}

namespace calcutfRate{
	CNatRateParam& GetNatRateParam(){
		static CNatRateParam stRateParam;
		return stRateParam;
	}
}